﻿using System;
using System.ComponentModel;
using System.Globalization;
using System.Web.UI;
using System.Web.UI.WebControls;
using AjaxControlToolkit;

namespace Portal.Api.Controls
{
  /// <summary>
  /// A Control for date and time input.
  /// </summary>
  [ToolboxData("<{0}:DateTimeControl runat=\"server\" />"), Designer("Portal.Api.Controls.DateTimeControlDesigner")]
  public class DateTimeControl : System.Web.UI.WebControls.WebControl, INamingContainer
  {
    TextBox _dateEdit;
    CalendarExtender _calendarExtender;
    TextBox _timeEdit;
    protected override void CreateChildControls()
    {
      base.CreateChildControls();

      // Create the Date Edit.
      _dateEdit = new TextBox();
      _dateEdit.Width = DateWith;
      _dateEdit.Height = Height;
      _dateEdit.Enabled = Enabled;
      _dateEdit.ID = "DateEdit";
      Controls.Add(_dateEdit);

      // Extend the edit with a calendar.
      _calendarExtender = new AjaxControlToolkit.CalendarExtender();
      _calendarExtender.TargetControlID = _dateEdit.ID;
      Controls.Add(_calendarExtender);

      // Extend the edit with a mask.
      MaskedEditExtender dateMask = new MaskedEditExtender();
      dateMask.ID = "DateMask";
      dateMask.TargetControlID = "DateEdit";
      dateMask.Mask = "99/99/9999";
      dateMask.OnInvalidCssClass = "InvalidDate";
      dateMask.MaskType = MaskedEditType.Date;
      Controls.Add(dateMask);

      // Extend the mask with a validator.
      MaskedEditValidator dateValidator = new MaskedEditValidator();
      dateValidator.ControlToValidate = "DateEdit";
      dateValidator.ControlExtender = "DateMask";
      dateValidator.IsValidEmpty = false;
      dateValidator.Display = ValidatorDisplay.Dynamic;
      dateValidator.EmptyValueMessage = "*";
      dateValidator.InvalidValueMessage = "*";
      Controls.Add(dateValidator);

      // If the time is supported, add a time edit field.
      if (TimeSupport)
      {
        Controls.Add(new LiteralControl("&nbsp;"));

        // Add a edit box for the time.
        _timeEdit = new TextBox();
        _timeEdit.Width = new Unit(Width.Value - DateWith.Value);
        _timeEdit.Height = Height;
        _timeEdit.ID = "TimeEdit";
        Controls.Add(_timeEdit);

        // Extend the editbox with a mask.
        MaskedEditExtender timeMask = new MaskedEditExtender();
        timeMask.ID = "TimeExtender";
        timeMask.TargetControlID = "TimeEdit";
        timeMask.Mask = "99:99";
        timeMask.MaskType = MaskedEditType.Time;
        timeMask.AcceptAMPM = true;
        timeMask.OnInvalidCssClass = "InvalidTime";
        Controls.Add(timeMask);

        // Extend the mask with a validator.
        MaskedEditValidator timeValidator = new MaskedEditValidator();
        timeValidator.ControlToValidate = "TimeEdit";
        timeValidator.ControlExtender = "TimeExtender";
        timeValidator.IsValidEmpty = !TimeRequired;
        timeValidator.Display = ValidatorDisplay.Dynamic;
        timeValidator.EmptyValueMessage = "*";
        timeValidator.InvalidValueMessage = "*";
        Controls.Add(timeValidator);
      }
    }

    public override Unit Height
    {
      get
      {
        return base.Height;
      }
      set
      {
        base.Height = value;
        if (_dateEdit != null)
          _dateEdit.Height = value;
      }
    }

    [DefaultValue("120px")]
    public override Unit Width
    {
      get
      {
        if (base.Width.IsEmpty)
          return Unit.Pixel(120);
        else
          return base.Width;
      }
      set
      {
        base.Width = value;
      }
    }

    [Bindable(true)]
    [Category("Layout")]
    [DefaultValue("70px")]
    [Localizable(true)]
    public Unit DateWith
    {
      get
      {
        if (TimeSupport)
        {
          if (null == ViewState["DateWith"])
            return Unit.Pixel(70);
          else
          {
            Unit calWith = (Unit)ViewState["DateWith"];
            if(calWith.IsEmpty)
              return Unit.Pixel(70);
            else
              return calWith;
          }
        }
        else
          return Width;
      }

      set
      {
        ViewState["DateWith"] = value;
      }
    }


    [Bindable(true)]
    [Category("Behavior")]
    [DefaultValue("true")]
    [Localizable(true)]
    public bool TimeSupport
    {
      get
      {
        if (null == ViewState["TimeSupport"])
          return true;
        else
          return bool.Parse(ViewState["TimeSupport"].ToString());
      }

      set
      {
        ViewState["TimeSupport"] = value;
      }
    }

    [Bindable(true)]
    [Category("Behavior")]
    [DefaultValue("true")]
    [Localizable(true)]
    public bool TimeRequired
    {
      get
      {
        if (null == ViewState["TimeRequired"])
          return true;
        else
          return bool.Parse(ViewState["TimeRequired"].ToString());
      }

      set
      {
        ViewState["TimeRequired"] = value;
      }
    }


    [Bindable(true)]
    [Category("Appearance")]
    [Localizable(true)]
    public DateTime DateTimeValue
    {
      get
      {
        DateTime dateValue;
        if (_dateEdit == null || string.IsNullOrEmpty(_dateEdit.Text))
        {
          dateValue = DateTime.Now;
        }
        else
        {
          if (!DateTime.TryParse(_dateEdit.Text, out dateValue))
            dateValue = DateTime.Now;
        }

        if (_timeEdit != null && TimeSupport)
        {
          DateTime time;
          if (string.IsNullOrEmpty(_timeEdit.Text))
            time = DateTime.Now;
          else
            time = DateTime.ParseExact(_timeEdit.Text, "t", CultureInfo.CurrentCulture);

          dateValue = new DateTime(dateValue.Year, dateValue.Month, dateValue.Day, time.Hour, time.Minute, 0);
        }
          
        return dateValue;
      }
      set
      {
        EnsureChildControls();
        _calendarExtender.SelectedDate = value;
        _timeEdit.Text = value.ToShortTimeString();
      }
    }
  }

  class DateTimeControlDesigner : System.Web.UI.Design.ControlDesigner
  {
    public override string GetDesignTimeHtml()
    {
      System.IO.StringWriter sw = new System.IO.StringWriter(CultureInfo.InvariantCulture);
      HtmlTextWriter tw = new HtmlTextWriter(sw);

      DateTimeControl ctrl = Component as DateTimeControl;

      TextBox textBox = new TextBox();
      textBox.Text = "Date";
      textBox.CssClass = ctrl.CssClass;
      textBox.Width = ctrl.DateWith;
      textBox.Height = ctrl.Height;
      textBox.Enabled = ctrl.Enabled;
      textBox.RenderControl(tw);

      if (ctrl.TimeSupport)
      {
        tw.Write("&nbsp;");

        textBox = new TextBox();
        textBox.Text = "Time";
        textBox.CssClass = ctrl.CssClass;
        textBox.Width = new Unit(ctrl.Width.Value - ctrl.DateWith.Value);
        textBox.Height = ctrl.Height;
        textBox.Enabled = ctrl.Enabled;
        textBox.RenderControl(tw);
      }

      return sw.ToString();

    }
  }
}
